home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Gold Medal Software 2
/
Gold Medal Software Volume 2 (Gold Medal) (1994).iso
/
graphics
/
rayl210.arj
/
RAYLATHE.C
< prev
next >
Wrap
Text File
|
1993-09-18
|
20KB
|
653 lines
/* RayLathe (c) Koehler
- Thick <0 = draw solid, =0 = move, >0 = draw hollow
Revision History:
03-24-93 1.00 KJK New. Inspired by uLathe.
03-28-93 1.01 KJK Attempting Vivid output for Doug Downs.
04-11-93 1.10 KJK Releasable Vivid output version.
Noticed THICK in Vivid no supported! Must fix if possible.
04-11-93 1.11 KJK Cured black speckles in POVRAY output.
04-14-93 1.12 KJK Allow 0 length cones (rings) for Vivid.
04-15-93 1.13 KJK Enable THICK for Vivid. Print line # of .DAT file.
04-24-93 1.20 KJK Since they are necessary when thickness is used,
simulate cone/rings for POVRAY.
06-28-93 1.?? esp Add POV-Ray 2.0 syntax, clean up cmdline parsing,
add Macintosh (MPW) support, change FP compares like (x==y)
to (fabs(x-y) < EPSILON) to better conform to
the way fp numbers (mis)behave, add tabwidth parm, clean up
indenting.
06-05-93 1.21 KJK First attempt at POVRAY triangles.
06-25-93 1.22 KJK Steve Anger replied to my message on YCCMR about
what vertex order is required!
07-10-93 1.23 KJK Steve Anger replied again. Problem was that data has
to be one whole object, not multiple objects.
07-11-93 1.24 KJK Combined Eduard Schwan's (esp) changes to 1.20 with
my 1.23. Removed double slash comments in code to
keep compatible with regular C. Its my understanding
the double slash is new for C++.
07-20-93 1.25 KJK Doug Downs said Vivid is OK, so lets do final cleanup.
Also, I will be looking into accepting color data
to pass along to the RAW converters.
Watch for seam in RAW output. I'm reluctant to fix what
I can't prove.
07-20-93 2.00 KJK Final release. You know, the one just before the bug fix
release. The verbose comments for all of the unreleased
versions are just an informational story. "It doesn't
matter, and so-what if it did!"
09-18-93 2.10 KJK Fix bug: Commas introduced by esp tabbing where they
didn't belong.
*/
/* ========================================================= */
/* INCLUDES */
#include <math.h>
#include <stdio.h> /* printf() */
#include <stdlib.h> /* exit() */
#include <string.h> /* strcmp() */
#include <ctype.h> /* tolower() */
/* ========================================================= */
/* DEFINES */
#define VERSION 2.10
#ifndef min
#define min(a,b) ((a)<(b) ? (a) : (b))
#define max(a,b) ((a)>(b) ? (a) : (b))
#endif
#define EPSILON 1.0e-10 /* miniscule fp number, essentially zero */
const double PI = 3.141592653589;
/* Raytracer output styles supported */
#define TRACER_VIVID 1
#define TRACER_POV10 2
#define TRACER_POV20 3
#define TRACER_RAW 4
#define DATA_OLD 0
#define DATA_SLICED -1
#define DATA_COLOR -2
#define TAB_WIDTH 4 /* default width */
/* ========================================================= */
/* PROTOTYPES */
static void show_usage(char *);
static void lathe_cut_viv(double, double, double, double, double);
static void lathe_cut_pov10(double, double, double, double, double);
static void lathe_cut_pov20(double, double, double, double, double);
static void lathe_tri_raw(double, double, double, double, double, unsigned char, double, double, double);
static void tab_printf(void);
static void tab_inc();
static void tab_dec();
static double intercept(double, double, double, double);
/* ========================================================= */
/* GLOBAL VARIABLES */
static int tab_width = TAB_WIDTH;
static int tab_level = 0;
/* ========================================================= */
int main(argc,argv)
int argc;
char *argv[];
{
int tracer = TRACER_POV10;
int line=0;
int k;
double oldx = 0.01, oldy = 0.01;
double x, y, thick;
double boundminx=1.0e8, boundmaxx=-1.0e8, boundmaxy=0.0;
double length, center, eye_distance;
double colorR = -1.0, colorG = -1.0, colorB = -1.0;
unsigned char slices = 8;
int datatype = DATA_OLD;
fprintf(stderr,"RayLathe v%2.2f (c) 1993 Koehler\n",VERSION);
/* Check the command line options ("/" for MSDOS, "-" for Unix & Mac) */
for (k=1; k<argc; k++)
{
/* this setup makes it easier to add new switches later */
switch (argv[k][0])
{
case '/':
case '-':
switch (tolower(argv[k][1]))
{
case '?':
show_usage(NULL);
break;
case 't':
tab_width = atoi(&argv[k][2]);
if ((tab_width < 1) || (tab_width > 16))
show_usage(argv[k]);
break;
case 'v':
tracer = TRACER_VIVID;
fprintf(stderr," Generating Vivid 2.0 object\n");
break;
case 'r':
tracer = TRACER_RAW;
fprintf(stderr," Generating Export (RAW) object\n");
break;
case 'p':
switch (argv[k][2])
{
case '1':
tracer = TRACER_POV10;
fprintf(stderr," Generating POV-Ray 1.0 object\n");
break;
case '2':
tracer = TRACER_POV20;
fprintf(stderr," Generating POV-Ray 2.0 object\n");
break;
default:
show_usage(argv[k]);
break;
}
break;
default:
show_usage(argv[k]);
break;
} /* switch */
break;
default:
show_usage(argv[k]);
break;
} /* switch */
} /* for */
/* write header */
switch (tracer)
{
case TRACER_VIVID:
printf("// Vivid 2.0 object created by RayLathe v%2.2f (c) 1993 Koehler\n",VERSION);
printf("// See overall dimensions of object at end of this file\n");
/* printf("// See suggested camera vectors at end of this file\n"); */
printf("\n");
break;
case TRACER_POV10:
printf("// POVRAY 1.0 object created by RayLathe v%2.2f (c) 1993 Koehler\n",VERSION);
printf("// See suggested camera vectors at end of this file\n\n");
printf("//#declare LatheWork =\n");
tab_inc();
tab_printf();printf("composite\n");
tab_printf();printf("{\n");
tab_inc();
break;
case TRACER_POV20:
printf("// POVRAY 2.0 object created by RayLathe v%2.2f (c) 1993 Koehler\n",VERSION);
printf("// See suggested camera vectors at end of this file\n\n");
printf("//#declare LatheWork =\n");
tab_inc();
tab_printf();printf("merge\n");
tab_printf();printf("{\n");
tab_inc();
break;
} /* switch */
/* Read first line from file */
scanf("%lf %lf %lf", &x, &y, &thick);
if (x < DATA_OLD) /* LAT2RAYL v1.00 didn't give slices, v1.10 does */
{
datatype = x;
slices = thick;
scanf("%lf %lf %lf", &x, &y, &thick);
}
if (datatype == DATA_COLOR)
scanf("%lf %lf %lf", &colorR, &colorG, &colorB);
line++;
/* loop through file */
do
{
if (tracer != TRACER_RAW)
{
tab_printf();printf("// ###\n");
tab_printf();printf("// ### Line %-4d (%lg, %lg, %lg)\n", line, x, y, thick);
}
if (thick)
{
switch (tracer)
{
case TRACER_VIVID:
lathe_cut_viv(oldx, oldy, x, y, thick);
break;
case TRACER_POV10:
lathe_cut_pov10(oldx, oldy, x, y, thick);
break;
case TRACER_POV20:
lathe_cut_pov20(oldx, oldy, x, y, thick);
break;
case TRACER_RAW:
lathe_tri_raw(oldx, oldy, x, y, thick, slices, colorR, colorG, colorB);
break;
} /* switch */
}
boundmaxx = max(boundmaxx, x);
boundminx = min(boundminx, x);
boundmaxy = max(boundmaxy, y);
oldx = x;
oldy = y;
/* read next line of file */
scanf("%lf %lf %lf", &x, &y, &thick);
if (datatype == DATA_COLOR)
scanf("%lf %lf %lf", &colorR, &colorG, &colorB);
line++;
} while ((x >= 0.0) || (y >= 0.0));
/* write trailer */
boundminx *= 1.001;
boundmaxx *= 1.001;
boundmaxy *= 1.001;
switch (tracer)
{
case TRACER_VIVID:
break;
case TRACER_POV10:
tab_printf();printf("bounded_by\n");
tab_printf();printf("{\n");
tab_inc();
tab_printf();printf("box { <%g %g %g> <%g %g %g> }\n",boundminx,-boundmaxy,-boundmaxy, boundmaxx, boundmaxy, boundmaxy);
tab_dec();
tab_printf();printf("}\n");
tab_dec();
tab_printf();printf("} // composite\n");
tab_dec();
length = boundmaxx - boundminx;
center = length / 2.0 + boundminx;
printf("\n#declare Look_At = <%g 0 0> // Center of object\n", center);
eye_distance = -max(fabs(length), boundmaxy*2.4);
printf("#declare Location = <%g 0 %g> // Good camera position\n", center, eye_distance);
break;
case TRACER_POV20:
tab_printf();printf("bounded_by\n");
tab_printf();printf("{\n");
tab_inc();
tab_printf();printf("box { <%g %g %g> <%g %g %g> }\n",boundminx,-boundmaxy,-boundmaxy, boundmaxx, boundmaxy, boundmaxy);
tab_dec();
tab_printf();printf("}\n");
tab_dec();
tab_printf();printf("} // union\n");
tab_dec();
length = boundmaxx - boundminx;
center = length / 2.0 + boundminx;
printf("\n#declare Look_At = <%g 0 0> // Center of object\n", center);
eye_distance = -max(fabs(length), boundmaxy*2.4);
printf("#declare Location = <%g 0 %g> // Good camera position\n", center, eye_distance);
break;
} /* switch */
if (tracer != TRACER_RAW)
printf("\n// Min X Y Z = %f %f %f Max X Y Z = %f %f %f\n",boundminx,-boundmaxy,-boundmaxy, boundmaxx, boundmaxy, boundmaxy);
return (0); /* Happy ANSI */
} /* main */
/* ========================================================= */
static void show_usage(char * opt)
{
if (opt != NULL)
fprintf(stderr,"### ERROR! Bad option '%s'\n", opt);
fprintf(stderr,"### Usage: raylathe [-v | -p1 | -p2 | -r] [-tN] <infile.dat >outfile.inc\n");
fprintf(stderr,"### where -v=Vivid, -p1=POV1.0, -p2=POV2.0, -r=RAW, -tN=tabwidth\n");
exit(1);
} /* show_usage */
/* ========================================================= */
static void lathe_cut_viv(x1, y1, x2, y2, thick)
double x1, y1, x2, y2, thick;
{
/* cone { base 1 1 1 base_radius 4 apex 0 0 5 apex_radius 1 } */
tab_printf();printf("cone { base %g 0.0 0.0 base_radius %g ", x1, y1);
tab_inc();
tab_printf();printf("apex %g 0.0 0.0 apex_radius %g }\n", x2, y2);
tab_dec();
if (thick > 0)
{
tab_printf();printf("cone { base %g 0.0 0.0 base_radius %g ", x1, max(y1-thick, 0.0));
tab_inc();
tab_printf();printf("apex %g 0.0 0.0 apex_radius %g }\n", x2, max(y2-thick, 0.0));
tab_dec();
tab_printf();printf("cone { base %g 0.0 0.0 base_radius %g ", x1, max(y1, 0.0));
tab_inc();
tab_printf();printf("apex %g 0.0 0.0 apex_radius %g }\n", x1, max(y1-thick, 0.0));
tab_dec();
tab_printf();printf("cone { base %g 0.0 0.0 base_radius %g ", x2, max(y2, 0.0));
tab_inc();
tab_printf();printf("apex %g 0.0 0.0 apex_radius %g }\n", x2, max(y2-thick, 0.0));
tab_dec();
}
} /* lathe_cut_viv */
/* ========================================================= */
static void lathe_cut_pov10(x1, y1, x2, y2, thick)
double x1, y1, x2, y2, thick;
{
double minx, miny, minz, maxx, maxy, maxz, origin;
if (fabs(x1-x2) < EPSILON)
if (fabs(thick) > EPSILON)
x1 = x1 * 1.001; /* Fudge a flat cone (ring) */
else
return;
minx = min(x1,x2);
maxx = max(x1,x2);
maxy = max(y1,y2);
miny = -maxy;
maxz = maxy;
minz = miny;
tab_printf();printf("object\n");
tab_printf();printf("{\n");
tab_inc();
tab_printf();printf("intersection\n");
tab_printf();printf("{\n");
tab_inc();
if (fabs(y1-y2) < EPSILON)
{
if (fabs(y1) > EPSILON)
{
tab_printf();printf("quadric { Cylinder_X scale <1 %g %g> }\n", y1, y1);
}
}
else
{
if ((fabs(x1) < EPSILON) || (fabs(x2) < EPSILON))
origin = 0;
else
origin=intercept(x1, y1, x2, y2);
tab_printf();printf("quadric { QCone_X ");
if (fabs(x1) < EPSILON)
{printf("scale <%g %g %g>", fabs(origin-x2), y2, y2);}
else
{printf("scale <%g %g %g>", fabs(origin-x1), y1, y1);}
printf(" translate <%g 0 0> }\n", origin);
}
if ((thick > 0.0) && (((y1-thick) > 0.0) || ((y2-thick) > 0.0)))
{
if (fabs(y1-y2) < EPSILON)
{
if ((y1-thick) > 0.0)
{
tab_printf();printf("quadric { Cylinder_X scale <1 %g %g> inverse }\n", y1-thick, y1-thick);
}
}
else
{
if ((fabs(x1) < EPSILON) || (fabs(x2) < EPSILON))
origin = 0;
else
origin = (((y1-thick)/y1)*(origin-x1))+x1;
tab_printf();printf("quadric { QCone_X ");
if (fabs(origin-x1) < EPSILON)
{printf("scale <%g %g %g>", fabs(origin-x2), y2-thick, y2-thick);}
else
{printf("scale <%g %g %g>", fabs(origin-x1), y1-thick, y1-thick);}
printf(" translate <%g 0 0> inverse }\n", origin);
}
}
tab_printf();printf("box { <%g %g %g> <%g %g %g> }\n",minx,miny,minz,maxx,maxy,maxz);
tab_dec();
tab_printf();printf("} // intersection\n");
minx = minx*1.001; /* Adjust for bounding */
maxx = maxx*1.001;
maxy = maxy*1.001;
miny = -maxy;
maxz = maxy;
minz = miny;
tab_printf();printf("bounded_by\n");
tab_printf();printf("{\n");
tab_inc();
tab_printf();printf("box { <%g %g %g> <%g %g %g> }\n",minx,miny,minz,maxx,maxy,maxz);
tab_dec();
tab_printf();printf("}\n");
tab_printf();printf("texture\n");
tab_printf();printf("{\n");
tab_inc();
tab_printf();printf("LatheWorkTex\n");
tab_dec();
tab_printf();printf("}\n");
tab_dec();
tab_printf();printf("} // object\n");
} /* lathe_cut_pov10 */
/* ========================================================= */
static void lathe_cut_pov20(x1, y1, x2, y2, thick)
double x1, y1, x2, y2, thick;
{
double minx, miny, minz, maxx, maxy, maxz, origin;
if (fabs(x1-x2) < EPSILON)
if (fabs(thick) > EPSILON)
x1 = x1 * 1.001; /* Fudge a flat cone (ring) */
else
return;
minx = min(x1,x2);
maxx = max(x1,x2);
maxy = max(y1,y2);
miny = -maxy;
maxz = maxy;
minz = miny;
tab_printf();printf("intersection\n");
tab_printf();printf("{\n");
tab_inc();
if (fabs(y1-y2) < EPSILON)
{
if (fabs(y1) > EPSILON)
{
tab_printf();printf("quadric { Cylinder_X scale <1 %g %g> }\n", y1, y1);
}
}
else
{
if ((fabs(x1) < EPSILON) || (fabs(x2) < EPSILON))
origin = 0;
else
origin=intercept(x1, y1, x2, y2);
tab_printf();printf("quadric { QCone_X ");
if (fabs(x1) < EPSILON)
{printf("scale <%g %g %g>", fabs(origin-x2), y2, y2);}
else
{printf("scale <%g %g %g>", fabs(origin-x1), y1, y1);}
printf(" translate %g*x }\n", origin);
}
if ((thick > 0.0) && (((y1-thick) > 0.0) || ((y2-thick) > 0.0)))
{
if (fabs(y1-y2) < EPSILON)
{
if ((y1-thick) > 0.0)
{
tab_printf();printf("quadric { Cylinder_X scale <1, %g %g> inverse }\n", y1-thick, y1-thick);
}
}
else
{
if ((fabs(x1) < EPSILON) || (fabs(x2) < EPSILON))
origin = 0;
else
origin = (((y1-thick)/y1)*(origin-x1))+x1;
tab_printf();printf("quadric { QCone_X ");
if (fabs(origin-x1) < EPSILON)
{printf("scale <%g %g %g>", fabs(origin-x2), y2-thick, y2-thick);}
else
{printf("scale <%g %g %g>", fabs(origin-x1), y1-thick, y1-thick);}
printf(" translate %g*x inverse }\n", origin);
}
}
tab_printf();printf("box { <%g %g %g> <%g %g %g> }\n",minx,miny,minz,maxx,maxy,maxz);
minx = minx*1.001; /* Adjust for bounding */
maxx = maxx*1.001;
maxy = maxy*1.001;
miny = -maxy;
maxz = maxy;
minz = miny;
tab_printf();printf("bounded_by\n");
tab_printf();printf("{\n");
tab_inc();
tab_printf();printf("box { <%g %g %g> <%g %g %g> }\n",minx,miny,minz,maxx,maxy,maxz);
tab_dec();
tab_printf();printf("}\n");
tab_printf();printf("texture\n");
tab_printf();printf("{\n");
tab_inc();
tab_printf();printf("LatheWorkTex\n");
tab_dec();
tab_printf();printf("}\n");
tab_dec();
tab_printf();printf("} // intersection\n");
} /* lathe_cut_pov20 */
/* ========================================================= */
static void lathe_tri_raw(x1, y1, x2, y2, thick, slices, colorR, colorG, colorB)
double x1, y1, x2, y2, thick, colorR, colorG, colorB;
unsigned char slices;
{
double byo, bzo, cy1, cz1, byi, bzi, cy3, cz3;
double ark, angle;
double pointy, pointz;
ark= (2 * PI / slices);
byo = 0; /* set outside for first pass */
bzo = y2;
cy1 = 0;
cz1 = y1;
byi = 0; /* same for inside */
bzi = y2-thick;
cy3 = 0;
cz3 = y1-thick;
for (angle=ark; angle<(2 * PI); angle+=ark)
{
pointy=sin(angle);
pointz=cos(angle);
if (y1 > 0)
{
if ( colorR >= 0)
printf("%g %g %g ", colorR, colorG, colorB);
/*A*/ printf("%g %g %g ", x1, (pointy*y1), (pointz*y1));
/*D*/ printf("%g %g %g ", x2, byo, bzo );
/*C*/ printf("%g %g %g\n", x1, cy1, cz1);
}
if (y2 > 0)
{
if ( colorR >= 0)
printf("%g %g %g ", colorR, colorG, colorB);
/*A*/ printf("%g %g %g ", x1, (pointy*y1), (pointz*y1) );
/*B*/ printf("%g %g %g ", x2, (pointy*y2), (pointz*y2));
/*D*/ printf("%g %g %g\n", x2, byo, bzo );
}
byo = (pointy*y2); /* update for next pass */
bzo = (pointz*y2);
cy1 = (pointy*y1);
cz1 = (pointz*y1);
if ((thick >= 0) && (((y1-thick)>0) || ((y2-thick)>0)))
{
if ((y1-thick) > 0)
{
if ( colorR >= 0)
printf("%g %g %g ", colorR, colorG, colorB);
/*A*/ printf("%g %g %g ", x1, (pointy*(y1-thick)), (pointz*(y1-thick)) );
/*D*/ printf("%g %g %g ", x2, byi, bzi );
/*C*/ printf("%g %g %g\n", x1, cy3, cz3);
}
if ((y2-thick) > 0)
{
if ( colorR >= 0)
printf("%g %g %g ", colorR, colorG, colorB);
/*A*/ printf("%g %g %g ", x1, (pointy*(y1-thick)), (pointz*(y1-thick)) );
/*B*/ printf("%g %g %g ", x2, (pointy*(y2-thick)), (pointz*(y2-thick)));
/*D*/ printf("%g %g %g\n", x2, byi, bzi );
}
byi = (pointy*(y2-thick)); /* update for next pass */
bzi = (pointz*(y2-thick));
cy3 = (pointy*(y1-thick));
cz3 = (pointz*(y1-thick));
}
}
}
/* ========================================================= */
static double intercept(x1, y1, x2, y2)
double x1, y1, x2, y2;
{
return(x2 - ((x2-x1) / (y2-y1) * y2));
} /* intercept */
/* ========================================================= */
static void tab_printf(void)
{
int k;
/* Q&D way to do it... */
for (k=0; k<tab_width*tab_level; k++)
putchar(' ');
} /* tab_printf */
/* ========================================================= */
static void tab_inc()
{
tab_level++;
} /* tab_inc */
/* ========================================================= */
static void tab_dec()
{
tab_level--;
if (tab_level < 0)
tab_level = 0;
} /* tab_dec */